package com.vision.sales.cm.db.data;

import java.io.Serializable;
import java.sql.Timestamp;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import net.sf.gilead.pojo.gwt.LightEntity;

import com.vision.core.cm.data.IHasSystemTime;
import com.vision.core.cm.db.data.Company;
import com.vision.sales.cm.data.IHasTransactionStatus;
import com.vision.sales.cm.data.PaymentType;
import com.vision.sales.cm.data.TransactionStatus;

/**
 * @author Mark
 * 
 */
@Entity
@Table(name = Collection.TABLE)
public class Collection extends LightEntity implements Serializable, IHasTransactionStatus, IHasSystemTime {
	
	public static interface FieldSpecs {
		int REF_NO_MAX = 30;
		int BANK_MAX = 100;
		int CHECK_NO_MAX = 30;
		int CASH_ACCOUNT_MAX = 100;
	}

	private static final long serialVersionUID = 568206672338006933L;
	
	// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	
	public static final String TABLE = "collection";
	
	public static final String COL_COMPANY_ID = "company_id";
	public static final String COL_ID = "id";
	public static final String COL_REF_NO = "ref_no";
	public static final String COL_CUSTOMER_ID = "customer_id";
	public static final String COL_COLLECTION_DATE = "collection_date";
	
	public static final String COL_PAYMENT_TYPE = "payment_type";
	
	public static final String COL_BANK = "bank";
	public static final String COL_CHECK_NO = "check_no";
	public static final String COL_CHECK_DATE = "check_date";
	public static final String COL_CASH_ACCOUNT = "cash_account";
	
	public static final String COL_GROSS_SALES = "gross_sales";
	public static final String COL_OVERRUNS = "overruns";
	public static final String COL_OVERPAYMENTS = "overpayments";
	public static final String COL_DISCOUNTS = "discounts";
	public static final String COL_REJECTS = "rejects";
	public static final String COL_RETURNS = "returns";
	
	public static final String COL_SUBTOTAL = "subtotal";
	public static final String COL_TAX = "tax";
	public static final String COL_NET_AMOUNT = "net_amount";
	
	public static final String COL_STATUS = "status";
	
	public static final String COL_SYS_CREATED = "sys_created";
	public static final String COL_SYS_LAST_MOD = "sys_last_mod";
	
	// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO, generator = "scollection")
	@SequenceGenerator(name = "scollection", sequenceName = "collection_seq")
	@Column(name = COL_ID)
	private Long id;
	
	@ManyToOne
	@JoinColumn(name = COL_COMPANY_ID, nullable = false)
	private Company company;
	
	@Column(name = COL_COLLECTION_DATE, nullable = false)
	@Temporal(TemporalType.DATE)
	private Date date;
	
	@Column(name = COL_REF_NO, nullable = false, unique = true, length = FieldSpecs.REF_NO_MAX)
	private String refNo;
	
	@ManyToOne
	@JoinColumn(name = COL_CUSTOMER_ID, nullable = false)
	private Customer customer;
	
	@Column(name = COL_PAYMENT_TYPE, nullable = false)
	@Enumerated(EnumType.STRING)
	private PaymentType paymentType;

	@Column(name = COL_BANK, length = FieldSpecs.BANK_MAX)
	private String bank;
	
	@Column(name = COL_CHECK_NO, length = FieldSpecs.CHECK_NO_MAX)
	private String checkNo;
	
	@Column(name = COL_CHECK_DATE)
	@Temporal(TemporalType.DATE)
	private Date checkDate;
	
	@Column(name = COL_CASH_ACCOUNT, length = FieldSpecs.CASH_ACCOUNT_MAX)
	private String cashAccount;
	
	@Column(name = COL_GROSS_SALES, nullable = false)
	private Double grossSales;
	
	@Column(name = COL_OVERRUNS, nullable = false)
	private Double overruns;
	
	@Column(name = COL_OVERPAYMENTS, nullable = false)
	private Double overpayments;
	
	@Column(name = COL_DISCOUNTS, nullable = false)
	private Double discounts;
	
	@Column(name = COL_REJECTS, nullable = false)
	private Double rejects;
	
	@Column(name = COL_RETURNS, nullable = false)
	private Double returns;
	
	@Column(name = COL_SUBTOTAL, nullable = false)
	private Double subtotal;
	
	@Column(name = COL_TAX, nullable = false)
	private Double tax;
	
	@Column(name = COL_NET_AMOUNT, nullable = false)
	private Double netAmount;
	
	@Column(name = COL_STATUS, nullable = false)
	@Enumerated(EnumType.STRING)
	private TransactionStatus status;
	
	@OneToMany(mappedBy = "collection", fetch = FetchType.LAZY, cascade = { CascadeType.MERGE })
	private Set<CollectionItem> collectionItems = new HashSet<CollectionItem>();
	
	// For internal use %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	
	/**
	 * The server {@link Timestamp} this object was created.
	 */
	@Column(name = COL_SYS_CREATED, nullable = false)
	private Timestamp sysCreated;
	
	/**
	 * The server {@link Timestamp} this object was last modified.
	 */
	@Column(name = COL_SYS_LAST_MOD, nullable = false)
	private Timestamp sysLastModified;
	
	// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

	public Collection() { }
	
	@Override
	public boolean equals(Object object) {
		if (object instanceof Collection)
		{
			Collection p = (Collection) object;
			return id.equals(p.id);
		}
		return false;
	}
	
	@Override
	public int hashCode() {
		return id == null ? super.hashCode() : id.hashCode();
	}
	
	@Override
	public String toString() {
		return id + ": " + refNo + "(" + date + ")";
	}
	
	// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

	public Company getCompany() {
		return company;
	}

	public void setCompany(Company company) {
		this.company = company;
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getRefNo() {
		return refNo;
	}

	public void setRefNo(String refNo) {
		this.refNo = refNo;
	}

	public Customer getCustomer() {
		return customer;
	}

	public void setCustomer(Customer customer) {
		this.customer = customer;
	}

	public Date getDate() {
		return date;
	}

	public void setDate(Date date) {
		this.date = date;
	}
	
	public PaymentType getPaymentType() {
		return paymentType;
	}
	
	public void setPaymentType(PaymentType paymentType) {
		this.paymentType = paymentType;
	}

	public String getBank() {
		return bank;
	}

	public void setBank(String bank) {
		this.bank = bank;
	}

	public String getCheckNo() {
		return checkNo;
	}

	public void setCheckNo(String checkNo) {
		this.checkNo = checkNo;
	}

	public Date getCheckDate() {
		return checkDate;
	}

	public void setCheckDate(Date checkDate) {
		this.checkDate = checkDate;
	}

	public String getCashAccount() {
		return cashAccount;
	}

	public void setCashAccount(String cashAccount) {
		this.cashAccount = cashAccount;
	}

	public Double getGrossSales() {
		return grossSales;
	}

	public void setGrossSales(Double grossSales) {
		this.grossSales = grossSales;
	}

	public Double getOverruns() {
		return overruns;
	}

	public void setOverruns(Double overruns) {
		this.overruns = overruns;
	}
	
	public Double getOverpayments() {
		return overpayments;
	}
	
	public void setOverpayments(Double overpayments) {
		this.overpayments = overpayments;
	}

	public Double getDiscounts() {
		return discounts;
	}

	public void setDiscounts(Double discounts) {
		this.discounts = discounts;
	}

	public Double getRejects() {
		return rejects;
	}

	public void setRejects(Double rejects) {
		this.rejects = rejects;
	}

	public Double getReturns() {
		return returns;
	}

	public void setReturns(Double returns) {
		this.returns = returns;
	}

	public Double getSubtotal() {
		return subtotal;
	}

	public void setSubtotal(Double subtotal) {
		this.subtotal = subtotal;
	}

	public Double getTax() {
		return tax;
	}

	public void setTax(Double tax) {
		this.tax = tax;
	}

	public Double getNetAmount() {
		return netAmount;
	}

	public void setNetAmount(Double netAmount) {
		this.netAmount = netAmount;
	}
	
	public TransactionStatus getStatus() {
		return status;
	}
	
	public void setStatus(TransactionStatus status) {
		this.status = status;
	}
	
	public Set<CollectionItem> getCollectionItems() {
		return collectionItems;
	}
	
	public void setCollectionItems(Set<CollectionItem> collectionItems) {
		this.collectionItems = collectionItems;
	}

	public Timestamp getSysCreated() {
		return sysCreated;
	}

	public void setSysCreated(Timestamp sysCreated) {
		this.sysCreated = sysCreated;
	}

	public Timestamp getSysLastModified() {
		return sysLastModified;
	}

	public void setSysLastModified(Timestamp sysLastModified) {
		this.sysLastModified = sysLastModified;
	}
	
}
